1 <!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
4 <meta http-equiv=
"Content-Type" content=
"text/html; charset=UTF-8">
5 <meta http-equiv=
"Content-Style-Type" content=
"text/css">
7 <meta name=
"Generator" content=
"Cocoa HTML Writer">
8 <meta name=
"CocoaVersion" content=
"1038.25">
9 <style type=
"text/css">
10 p
.p1
{margin: 0.0px 0.0px 0.0px 0.0px; font: 20.0px Helvetica
}
11 p
.p2
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
; min-height: 14.0px}
12 p
.p3
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
}
13 p
.p4
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
}
14 p
.p5
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; min-height: 12.0px}
15 p
.p6
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #bf0000}
16 p
.p7
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #007300}
17 p
.p8
{margin: 0.0px 0.0px 0.0px 0.0px; font: 14.0px Helvetica
}
18 p
.p9
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
; color: #bf0000}
19 p
.p10
{margin: 0.0px 0.0px 0.0px 0.0px; font: 9.0px Monaco
; color: #0000bf}
20 p
.p11
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
; color: #0000ee}
21 li
.li3
{margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica
}
22 span
.s1
{color: #0000bf}
23 span
.s2
{color: #bf0000}
24 span
.s3
{color: #000000}
25 span
.s4
{color: #007300}
26 span
.s5
{text-decoration: line-through
}
27 span
.s6
{font: 12.0px Helvetica
}
28 span
.Apple-tab-span
{white-space:pre
}
29 ul
.ul1
{list-style-type: disc
}
30 ul
.ul2
{list-style-type: circle
}
34 <p class=
"p1"><b>What's that Pbind thing?
</b></p>
35 <p class=
"p2"><br></p>
36 <p class=
"p3">Some of the examples in the last tutorial played notes using Pbind, and you might be wondering how it works in general and what else you can do with it.
</p>
37 <p class=
"p2"><br></p>
38 <p class=
"p3">In the most general sense,
<a href=
"../Patterns/Pbind.html"><span class=
"s1">Pbind
</span></a> is just a way to give names to values coming out of the types of patterns we just saw. When you ask a Pbind stream for its next value, the result is an object called an
<a href=
"../../Collections/Event.html"><span class=
"s1">Event
</span></a>. Like a
<a href=
"../../Collections/Dictionary.html"><span class=
"s1">Dictionary
</span></a> (which is a superclass of Event), an event is a set of
"key-value pairs": each value is named by a key.
</p>
39 <p class=
"p2"><br></p>
40 <p class=
"p4">e = (freq:
440, dur:
0.5);
<span class=
"Apple-tab-span"> </span><span class=
"s2">// an Event
</span></p>
41 <p class=
"p5"><br></p>
42 <p class=
"p6"><span class=
"s3">e.at(
</span><span class=
"s4">\freq
</span><span class=
"s3">)
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// access a value by name
</p>
43 <p class=
"p7"><span class=
"s3">e[
</span>\freq
<span class=
"s3">]
</span></p>
44 <p class=
"p6"><span class=
"s3">e.freq
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// See IdentityDictionary help for more on this usage
</p>
45 <p class=
"p5"><br></p>
46 <p class=
"p6"><span class=
"s3">e.put(
</span><span class=
"s4">\freq
</span><span class=
"s3">,
880);
<span class=
"Apple-tab-span"> </span></span>// Change a value by name
</p>
47 <p class=
"p4">e[
<span class=
"s4">\freq
</span>] =
660;
</p>
48 <p class=
"p4">e.freq =
220;
</p>
49 <p class=
"p5"><br></p>
50 <p class=
"p6"><span class=
"s3">e.put(
</span><span class=
"s4">\amp
</span><span class=
"s3">,
0.6);
<span class=
"Apple-tab-span"> </span></span>// Add a new value into the event
</p>
51 <p class=
"p6"><span class=
"s3">e.put(
</span><span class=
"s4">\dur
</span><span class=
"s3">,
</span><span class=
"s1">nil
</span><span class=
"s3">);
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// Remove a value
</p>
52 <p class=
"p2"><br></p>
53 <p class=
"p3">A Pbind is defined by a list of pairs: keys associated with the patterns that will supply the values for the events.
</p>
54 <p class=
"p2"><br></p>
55 <p class=
"p3">Things get interesting when the names associated with Pbind's sub-patterns are also
<a href=
"../../ServerArchitecture/SynthDef.html"><span class=
"s1">SynthDef
</span></a> arguments. Then it becomes possible to play new Synths with Pbind, and feed their inputs with different values on each event.
</p>
56 <p class=
"p2"><br></p>
57 <p class=
"p8"><b>Building an event, one key at a time
</b></p>
58 <p class=
"p2"><br></p>
59 <p class=
"p3">We can look at the return values from a Pbind by calling next on the stream. Note that it's necessary to pass an empty event into
<i>next
</i>, so that Pbind has somewhere to put the values.
</p>
60 <p class=
"p2"><br></p>
62 <p class=
"p4">p =
<span class=
"s1">Pbind
</span>(
</p>
63 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s4">\degree
</span>,
<span class=
"s1">Pseq
</span>(#[
0,
0,
4,
4,
5,
5,
4],
1),
</p>
64 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s4">\dur
</span>,
<span class=
"s1">Pseq
</span>(#[
0.5,
0.5,
0.5,
0.5,
0.5,
0.5,
1],
1)
</p>
65 <p class=
"p6"><span class=
"s3">).asStream;
<span class=
"Apple-tab-span"> </span></span>// remember, you have to make a stream out of the pattern before using it
</p>
67 <p class=
"p5"><br></p>
68 <p class=
"p6"><span class=
"s3">p.next(
</span><span class=
"s1">Event
</span><span class=
"s3">.new);
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// shorter: p.next(())
</p>
69 <p class=
"p5"><br></p>
70 <p class=
"p6">// Output:
</p>
71 <p class=
"p4">( 'degree':
0, 'dur':
0.5 )
</p>
72 <p class=
"p4">( 'degree':
0, 'dur':
0.5 )
</p>
73 <p class=
"p4">( 'degree':
4, 'dur':
0.5 )
</p>
74 <p class=
"p4">( 'degree':
4, 'dur':
0.5 )
</p>
75 <p class=
"p2"><br></p>
76 <p class=
"p3">The return events show us what Pbind really does. Each time the next value is requested, it goes through each key-pattern pair and gets the next value from each pattern (actually streams, but Pbind makes streams out of the sub patterns internally). Each value gets put into the event, using the associated key.
</p>
77 <p class=
"p2"><br></p>
78 <p class=
"p3">For the first event, the first key is 'degree' and the value is
0. This is placed into the event before moving to the next pair: the event in transition contains ( 'degree':
0 ). Then the next key supplies
0.5 for 'dur', and since there are no more pairs, the event is complete: ( 'degree':
0, 'dur':
0.5 ).
</p>
79 <p class=
"p2"><br></p>
80 <p class=
"p9">// User does:
</p>
81 <p class=
"p4">p.next(
<span class=
"s1">Event
</span>.new);
</p>
82 <p class=
"p2"><br></p>
83 <p class=
"p9">// SuperCollider processes:
</p>
84 <p class=
"p3">1. \degree stream returns
0</p>
85 <p class=
"p3">2. Put it in the Event: ( 'degree':
0 )
</p>
86 <p class=
"p3">3. \dur stream returns
0.5</p>
87 <p class=
"p3">4. Put it in the Event: ( 'degree':
0, 'dur':
0.5 )
</p>
88 <p class=
"p3">5. Return the result event.
</p>
89 <p class=
"p2"><br></p>
90 <p class=
"p3"><b>Note:
</b> Dictionaries in SuperCollider are
<i>unordered
</i> collections. Even though Pbind processes its child streams in the order given, the results can display the keys and values in any order. This does not affect the behavior of playing Events, as we will soon see.
</p>
91 <p class=
"p2"><br></p>
92 <p class=
"p2"><br></p>
93 <p class=
"p8"><b>Event, .play and event prototypes
</b></p>
94 <p class=
"p2"><br></p>
95 <p class=
"p3">So far we haven't seen anything that produces a note, just data processing: fetching values from patterns and stitching them together into events. The notes come from the difference between Events and regular Dictionaries: Events can do things when you
<b>.play
</b> them.
</p>
96 <p class=
"p2"><br></p>
97 <p class=
"p4">( 'degree':
0, 'dur':
0.5 ).play;
</p>
98 <p class=
"p2"><br></p>
99 <p class=
"p3">The action that the event will take is defined in an
"event prototype." The prototype must include a function for the 'play' key; this function is executed when .play is called on the event. Also, optionally the prototype can contain default values for a wide variety of parameters.
</p>
100 <p class=
"p2"><br></p>
101 <p class=
"p3">Pbind doesn't do much without an event prototype. Fortunately, you don't have to write the prototype on your own. There is a default event, accessed by Event.default, that includes functions for many different server-messaging tasks. If no specific action is requested, the normal action is to play a Synth. That's why playing a Pbind, as in the previous tutorial, with only 'degree' and 'dur' patterns produced notes: each event produces at least one synth by default, and the default event prototype knows how to convert scale degrees into frequencies and 'dur' (duration) into note lengths.
</p>
102 <p class=
"p2"><br></p>
103 <p class=
"p3">When a pattern is played, an object called EventStreamPlayer is created. This object reads out the events one by one from the pattern's stream (using a given event prototype as the base), and calls 'play' on each. The 'delta' value in the event determines how many beats to wait until the next event. Play continues until the pattern stops producing events, or you call .stop on the EventStreamPlayer. (Note that calling .stop on the pattern does nothing. Patterns are stateless and cannot play or stop by themselves.)
</p>
104 <p class=
"p2"><br></p>
105 <p class=
"p3"><b>To sum up so far:
</b> A Pbind's stream generates Events. When an Event is played, it does some work that usually makes noise on the server. This work is defined in an event prototype. The Event class provides a default event prototype that includes powerful options to create and manipulate objects on the server.
</p>
106 <p class=
"p2"><br></p>
107 <p class=
"p2"><br></p>
108 <p class=
"p3"><b>Useful Pbind variant: Pmono
</b></p>
109 <p class=
"p2"><br></p>
110 <p class=
"p3">Pbind plays separate notes by default. Sometimes, you might need a pattern to act more like a monophonic synthesizer, where it plays just one Synth node and changes its values with each event. If Pbind normally corresponds to Synth.new or /s_new,
<a href=
"../Patterns/Pmono.html"><span class=
"s1">Pmono
</span></a> corresponds to aSynth.set or /n_set.
</p>
111 <p class=
"p2"><br></p>
112 <p class=
"p3">Compare the sound of these patterns. Pbind produces an attack on every note, while Pmono glides from pitch to pitch.
</p>
113 <p class=
"p2"><br></p>
114 <p class=
"p4">p =
<span class=
"s1">Pbind
</span>(
<span class=
"s4">\degree
</span>,
<span class=
"s1">Pwhite
</span>(
0,
7,
<span class=
"s1">inf
</span>),
<span class=
"s4">\dur
</span>,
0.25,
<span class=
"s4">\legato
</span>,
1).play;
</p>
115 <p class=
"p4">p.stop;
</p>
116 <p class=
"p5"><br></p>
117 <p class=
"p4">p =
<span class=
"s1">Pmono
</span>(
<span class=
"s4">\default
</span>,
<span class=
"s4">\degree
</span>,
<span class=
"s1">Pwhite
</span>(
0,
7,
<span class=
"s1">inf
</span>),
<span class=
"s4">\dur
</span>,
0.25).play;
</p>
118 <p class=
"p4">p.stop;
</p>
119 <p class=
"p2"><br></p>
120 <p class=
"p3">Articulating phrases is possible with Pmono by chaining several Pmono patterns together in a row, or by using
<a href=
"../Patterns/PmonoArtic.html"><span class=
"s1">PmonoArtic
</span></a>.
</p>
121 <p class=
"p2"><br></p>
122 <p class=
"p2"><br></p>
123 <p class=
"p8"><b>Connecting Event values to SynthDef inputs
</b></p>
124 <p class=
"p2"><br></p>
125 <p class=
"p3">Most SynthDefs have
<a href=
"../../UGens/Synth control/Control.html"><span class=
"s1">Control
</span></a> inputs, usually defined by arguments to the UGen function. For example, the default SynthDef (declared in Event.sc) defines five inputs: out, freq, amp, pan and gate.
</p>
126 <p class=
"p2"><br></p>
127 <p class=
"p4"><span class=
"s1">SynthDef
</span>(
<span class=
"s4">\default
</span>, {
<span class=
"s1">arg
</span> out=
0, freq=
440, amp=
0.1, pan=
0, gate=
1;
</p>
128 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s1">var
</span> z;
</p>
129 <p class=
"p4"><span class=
"Apple-tab-span"> </span>z =
<span class=
"s1">LPF
</span>.ar(
</p>
130 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s1">Mix
</span>.new(
<span class=
"s1">VarSaw
</span>.ar(freq + [
0,
<span class=
"s1">Rand
</span>(-
0.4,
0.0),
<span class=
"s1">Rand
</span>(
0.0,
0.4)],
0,
0.3)),
</p>
131 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s1">XLine
</span>.kr(
<span class=
"s1">Rand
</span>(
4000,
5000),
<span class=
"s1">Rand
</span>(
2500,
3200),
1)
</p>
132 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>) *
<span class=
"s1">Linen
</span>.kr(gate,
0.01,
0.7,
0.3,
2);
</p>
133 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s1">OffsetOut
</span>.ar(out,
<span class=
"s1">Pan2
</span>.ar(z, pan, amp));
</p>
134 <p class=
"p4">}, [
<span class=
"s4">\ir
</span>]);
</p>
135 <p class=
"p2"><br></p>
136 <p class=
"p3">When an event plays a synth, any values stored in the event under the same name as a SynthDef input will be passed to the new synth. Compare the following:
</p>
137 <p class=
"p2"><br></p>
138 <p class=
"p6">// Similar to Synth(\default, [freq:
293.3333, amp:
0.2, pan: -
0.7])
</p>
139 <p class=
"p4">(freq:
293.3333, amp:
0.2, pan: -
0.7).play;
</p>
140 <p class=
"p5"><br></p>
141 <p class=
"p6">// Similar to Synth(\default, [freq:
440, amp:
0.1, pan:
0.7])
</p>
142 <p class=
"p4">(freq:
440, amp:
0.1, pan:
0.7).play;
</p>
143 <p class=
"p2"><br></p>
144 <p class=
"p3">This leads to a key point:
<b>The names that you use for patterns in Pbind should correspond to the arguments in the SynthDef being played.
</b> The Pbind pattern names determine the names for values in the resulting Event, and those values are sent to the corresponding Synth control inputs.
</p>
145 <p class=
"p2"><br></p>
146 <p class=
"p3">The SynthDef to play is named by the 'instrument' key. To play a pattern using a different Synth, simply name it in the pattern.
</p>
147 <p class=
"p2"><br></p>
148 <p class=
"p10">SynthDef
<span class=
"s3">(
</span><span class=
"s4">\harpsi
</span><span class=
"s3">, {
</span>|outbus =
0, freq =
440, amp =
0.1, gate =
1|
</p>
149 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s1">var
</span> out;
</p>
150 <p class=
"p4"><span class=
"Apple-tab-span"> </span>out =
<span class=
"s1">EnvGen
</span>.ar(
<span class=
"s1">Env
</span>.adsr, gate, doneAction:
2) * amp *
</p>
151 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"s1">Pulse
</span>.ar(freq,
0.25,
0.75);
</p>
152 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s1">Out
</span>.ar(outbus, out !
2);
</p>
153 <p class=
"p6"><span class=
"s3">}).add;
<span class=
"Apple-tab-span"> </span></span>// see below for more on .add
</p>
154 <p class=
"p5"><br></p>
155 <p class=
"p4">p =
<span class=
"s1">Pbind
</span>(
</p>
156 <p class=
"p6"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// Use \harpsi, not \default
</p>
157 <p class=
"p7"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span>\instrument
<span class=
"s3">,
</span>\harpsi
<span class=
"s3">,
</span></p>
158 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s4">\degree
</span>,
<span class=
"s1">Pseries
</span>(
0,
1,
8),
</p>
159 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s4">\dur
</span>,
0.25</p>
160 <p class=
"p4">).play;
</p>
161 <p class=
"p2"><br></p>
162 <p class=
"p3">It's actually an oversimplification to say that the Pbind names should always match up to SynthDef arguments.
</p>
163 <p class=
"p2"><br></p>
165 <li class=
"li3">A Pbind can use some values in the event for intermediate calculations (see
<a href=
"PG_06g_Data_Sharing.html"><span class=
"s1">PG_06g_Data_Sharing
</span></a>). If these intermediate values have names not found in the SynthDef, they are not sent to the server. There is no requirement that every item in an Event must correspond to a SynthDef control.
</li>
166 <li class=
"li3">The default event prototype performs some automatic conversions. You might have noticed that the examples so far use 'degree' to specify pitch, but the default SynthDef being played does not have a degree argument. It works because the default event converts degree into 'freq', which is an argument. The most important conversions are for pitch and timing. Timing is simple; pitch is more elaborate. See
<a href=
"PG_07_Value_Conversions.html"><span class=
"s1">PG_07_Value_Conversions
</span></a> for an explanation of these automatic calculations.
</li>
168 <p class=
"p2"><br></p>
169 <p class=
"p3"><b>Don't send or load SynthDefs; use .add or .store instead
</b></p>
170 <p class=
"p2"><br></p>
171 <p class=
"p3">To send only the relevant values to the new Synth, the Event needs to know what controls exist in the SynthDef. This is done by a library of descriptors for SynthDefs; the descriptor is a
<a href=
"../../ServerArchitecture/SynthDesc.html"><span class=
"s1">SynthDesc
</span></a>, and the library is a
<a href=
"../../ServerArchitecture/SynthDescLib.html"><span class=
"s1">SynthDescLib
</span></a>. The normal methods -- .send(s), .load(s) -- to communicate a SynthDef to the server do not enter it into the library. As a result, SynthDefs sent this way will not work properly with Pbind. Instead, use different methods that
<i>store
</i> the SynthDef into the library.
</p>
172 <p class=
"p2"><br></p>
173 <p class=
"p6">// Save into the library, write a .scsyndef file, and load it on the server
</p>
174 <p class=
"p4"><span class=
"s1">SynthDef
</span>(...).store;
</p>
175 <p class=
"p5"><br></p>
176 <p class=
"p6">// Save into the library and send the SynthDef to the server (no .scsyndef file)
</p>
177 <p class=
"p6">// Make sure the server is booted before doing this
</p>
178 <p class=
"p4"><span class=
"s1">SynthDef
</span>(...).add;
</p>
179 <p class=
"p2"><br></p>
180 <p class=
"p3"><span class=
"s5">.load(s)
</span><span class=
"Apple-tab-span"> </span>--
><span class=
"Apple-tab-span"> </span>.store
</p>
181 <p class=
"p3"><span class=
"s5">.send(s)
</span><span class=
"Apple-tab-span"> </span>--
><span class=
"Apple-tab-span"> </span>.add
</p>
182 <p class=
"p2"><br></p>
183 <p class=
"p2"><br></p>
184 <p class=
"p8"><b>“Rest” events
</b></p>
185 <p class=
"p2"><br></p>
186 <p class=
"p3">The convention to include a rest in the middle of an event pattern is to set the \freq key to a Symbol. Commonly this is \rest, but a backslash by itself is enough to suppress the note on the server. Ligeti's
"touches bloquées" technique could be written this way (see
<a href=
"PG_06e_Language_Control.html"><span class=
"s1">PG_06e_Language_Control
</span></a> for an explanation of the conditional
<a href=
"../Patterns/Pif.html"><span class=
"s1">Pif
</span></a>):
</p>
187 <p class=
"p2"><br></p>
189 <p class=
"p6">// first, pitches ascending by
1-
3 semitones, until
2 octaves are reached
</p>
190 <p class=
"p4"><span class=
"s1">var
</span><span class=
"Apple-tab-span"> </span>pitches =
<span class=
"s1">Pseries
</span>(
0,
<span class=
"s1">Pconst
</span>(
24,
<span class=
"s1">Pwhite
</span>(
1,
3,
<span class=
"s1">inf
</span>)),
<span class=
"s1">inf
</span>).asStream.all,
</p>
191 <p class=
"p6"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// randomly block
1/
3 of those
</p>
192 <p class=
"p4"><span class=
"Apple-tab-span"> </span>mask = pitches.scramble[
0 .. pitches.size div:
3];
</p>
193 <p class=
"p5"><br></p>
194 <p class=
"p4">p =
<span class=
"s1">Pbind
</span>(
</p>
195 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s4">\arpeg
</span>,
<span class=
"s1">Pseq
</span>(pitches[ .. pitches.size -
2] ++ pitches.reverse[ .. pitches.size -
2],
<span class=
"s1">inf
</span>),
</p>
196 <p class=
"p6"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// if the note is found in the mask array, replace it with \rest
</p>
197 <p class=
"p6"><span class=
"s3"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span></span>// then that note does not sound
</p>
198 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s4">\note
</span>,
<span class=
"s1">Pif
</span>(
<span class=
"s1">Pfunc
</span> {
<span class=
"s1">|event|
</span> mask.includes(event[
<span class=
"s4">\arpeg
</span>]) },
<span class=
"s4">\rest
</span>,
<span class=
"s1">Pkey
</span>(
<span class=
"s4">\arpeg
</span>)),
</p>
199 <p class=
"p7"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span>\octave
<span class=
"s3">,
4,
</span></p>
200 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s4">\dur
</span>,
0.125</p>
201 <p class=
"p4">).play;
</p>
203 <p class=
"p5"><br></p>
204 <p class=
"p4">p.stop;
</p>
205 <p class=
"p2"><br></p>
206 <p class=
"p3">If it's the \freq key that determines whether the event as a rest or not, why does it work to use it with \note? As noted, keys like \degree, \note, and \midinote are automatically converted into frequency. The math operations that perform the conversion preserve Symbols intact -- e.g., \rest +
1 == \rest. So the \rest value is passed all the way through the chain of conversions so that \freq in the event ends up receiving \rest.
</p>
207 <p class=
"p2"><br></p>
208 <p class=
"p3">Note that it doesn't matter if the SynthDef has a 'freq' argument. It's the event, on the
<i>client
</i> side, that looks to this key to determine whether to play the note or not. If it is a rest, the server is not involved at all.
</p>
209 <p class=
"p2"><br></p>
210 <p class=
"p2"><br></p>
211 <p class=
"p8"><b>Writing SynthDefs for patterns
</b></p>
212 <p class=
"p2"><br></p>
213 <p class=
"p3">SynthDefs should have a couple of specific features to work well with patterns.
</p>
214 <p class=
"p2"><br></p>
215 <p class=
"p3"><b>Synths should release themselves
</b></p>
216 <p class=
"p2"><br></p>
217 <p class=
"p3">The default event prototype relies on the synth to remove itself from the server when it's finished. This can be done in several ways:
</p>
218 <p class=
"p2"><br></p>
220 <li class=
"li3">(Most typical) A gated envelope with a releasing doneAction (
>=
2) in the envelope generator (see
<a href=
"../../UGens/Synth control/Envelopes/UGen-doneActions.html"><span class=
"s1">UGen-doneActions
</span></a> for a complete list). The \harpsi SynthDef above uses this technique. A gated envelope specifies a release node or uses one of the predefined sustaining envelope types: Env.asr, Env.adsr, Env.dadsr. The Env help file offers more detail on gated envelopes.
</li>
221 <li class=
"li3">Linen.kr, which is a shortcut for EnvGen.kr(Env([
0, susLevel,
0], [attackTime, releaseTime], \lin, releaseNode:
1), gate, doneAction: [
2 or higher]). The default SynthDef uses this. The doneAction should be at least
2 to release the node.
</li>
223 <li class=
"li3"><b>Note:
</b> If the release is controlled by a gate, the gate must be represented by the synth argument 'gate'; standard event prototypes expect to be able to control the synth's release using this argument. Also, make sure the gate's default value is greater than
0. Otherwise, the envelope will never start and you will both hear nothing and watch synths pile up on the server.
</li>
225 <li class=
"li3">Fixed-duration envelopes (no gate).
</li>
227 <p class=
"p2"><br></p>
228 <p class=
"p2"><br></p>
229 <p class=
"p3"><b>Argument name prefixes
</b></p>
230 <p class=
"p2"><br></p>
231 <p class=
"p3">One other subtle point about synth argument names. In a SynthDef, argument names can have the prefix
<b>t_
</b> to indicate a
"trigger control," or
<b>i_
</b> for an
"initial rate" control (meaning that it holds the value set when the Synth is first played). This is described in
<a href=
"../../ServerArchitecture/SynthDef.html"><span class=
"s1">SynthDef
</span></a> help. Pbind and its cousins should leave out the prefixes, e.g.:
</p>
232 <p class=
"p2"><br></p>
234 <p class=
"p10">SynthDef
<span class=
"s3">(
</span><span class=
"s4">\trig_demo
</span><span class=
"s3">, {
</span>|freq, gate =
1, t_trig =
1|
<span class=
"s3"><span class=
"Apple-tab-span"> </span></span><span class=
"s2">// t_trig here
</span></p>
235 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s1">var
</span><span class=
"Apple-tab-span"> </span>env =
<span class=
"s1">Decay2
</span>.kr(t_trig,
0.01,
0.1),
</p>
236 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>sig =
<span class=
"s1">SinOsc
</span>.ar(freq,
0, env)
</p>
237 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span>*
<span class=
"s1">Linen
</span>.kr(gate,
0.01,
0.1,
0.1, doneAction:
2);
</p>
238 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s1">Out
</span>.ar(
0, sig !
2)
</p>
239 <p class=
"p4">}).add;
</p>
241 <p class=
"p5"><br></p>
243 <p class=
"p7"><span class=
"s3">p =
</span><span class=
"s1">Pmono
</span><span class=
"s3">(
</span>\trig_demo
<span class=
"s3">,
</span></p>
244 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s4">\freq
</span>,
<span class=
"s1">Pexprand
</span>(
200,
800,
<span class=
"s1">inf
</span>),
</p>
245 <p class=
"p6"><span class=
"s3"><span class=
"Apple-tab-span"> </span></span><span class=
"s4">\trig
</span><span class=
"s3">,
1,
<span class=
"Apple-tab-span"> </span></span>// note that this is NOT t_trig -- just \trig
</p>
246 <p class=
"p4"><span class=
"Apple-tab-span"> </span><span class=
"s4">\delta
</span>,
0.125</p>
247 <p class=
"p4">).play;
</p>
249 <p class=
"p5"><br></p>
250 <p class=
"p4">p.stop;
</p>
251 <p class=
"p2"><br></p>
252 <p class=
"p2"><br></p>
253 <p class=
"p11"><span class=
"s3">Previous:
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><a href=
"PG_02_Basic_Vocabulary.html"><span class=
"s6">PG_02_Basic_Vocabulary
</span></a></span></p>
254 <p class=
"p11"><span class=
"s3">Next:
<span class=
"Apple-tab-span"> </span><span class=
"Apple-tab-span"> </span><a href=
"PG_04_Words_to_Phrases.html"><span class=
"s6">PG_04_Words_to_Phrases
</span></a></span></p>